Option Strict Off
Option Explicit On

Imports System.IO
Imports System.Globalization

Namespace SDIFChecker

    Module Check

        Public gbBreak As Boolean
        Public iDGVRow As Short
        Public iDGVMaxRow As Short
        Public sDGVRow As String
        Public SDIFErrorCount As Short

        Function CheckSDIF(ByRef tFile As String, ByRef tVersion As String) As Boolean
            Dim tStr As String = ""
            Dim FileNumber As Short
            Dim I As Short

            On Error Resume Next

            CheckSDIF = False
            gbBreak = False
            I = LoadSDIFDDL(tVersion)

            If I = -1 Then
                SDIFChecker.UnSetHourglass()
                tStr = "Error: """ & tVersion & """ definition file not found!" & vbCrLf & vbCrLf
                tStr = tStr & "This file must be in """ & My.Application.Info.DirectoryPath & """ in order to import " & vbCrLf
                tStr = tStr & "successfully."
                MsgBox(tStr, MsgBoxStyle.Critical)
                CheckSDIF = True
                Exit Function
            ElseIf I > 1 Then
                SDIFChecker.UnSetHourglass()
                tStr = "Error: """ & tVersion & """ definition file is corrupted!" & vbCrLf & vbCrLf
                tStr = tStr & "This file has a format error on that needs correcting!" & vbCrLf
                tStr = tStr & vbCrLf & "Line(" & CStr(I) & ")=" & gsString
                MsgBox(tStr, MsgBoxStyle.Critical)
                CheckSDIF = True
                Exit Function
            End If

            frmMain.ProgressBar1.Value = 0
            giSDIFRec = 0
            giError = 0

            If SDIFErrorCount > 0 Then
                SDIFErrorCount = 0
                frmMain.LoadSDIFImportGrid(SDIFChecker.gsSDIFName)
                'For iDGVRow = frmMain.DataGridView1.RowCount - 1 To 0 Step -1
                '    Dim sCnt As String = frmMain.DataGridView1.Rows(iDGVRow).Cells(0).Value.ToString
                '    If sCnt.Length = 0 Then
                '        frmMain.DataGridView1.Rows.RemoveAt(iDGVRow)
                '    End If
                'Next iDGVRow
            End If

            iDGVMaxRow = frmMain.DataGridView1.RowCount - 1
            frmMain.ProgressBar1.Maximum = iDGVMaxRow
            iDGVRow = 0
            I = 0

            While iDGVRow < iDGVMaxRow
                If gbBreak = True Then
                    Exit While
                End If
                If frmMain.DataGridView1.Rows(iDGVRow).Cells(0).Value.ToString.Length > 0 Then
                    sDGVRow = frmMain.DataGridView1.Rows(iDGVRow).Cells(1).Value
                    I += 1
                    If Check_SDIF(sDGVRow) = True Then
                        Exit While
                    End If
                End If
                frmMain.ProgressBar1.Value = I
                If (iDGVRow Mod 10) = 0 Then
                    frmMain.lblCount.Text = VB6.Format(I, "####")
                    System.Windows.Forms.Application.DoEvents()
                End If
                giSDIFRec += 1
                iDGVRow += 1
            End While

            frmMain.lblCount.Text = VB6.Format(I + 1, "####")

            tStr = frmMain.DataGridView1.Rows(iDGVRow).Cells(1).Value
            If Left(tStr, 2) <> "Z0" Then
                SDIF_Error("Last record must be a ""Z0""-type record!", 1, 2, SDIF_CRITICAL)
            End If

        End Function

        Function Check_SDIF(ByRef tStr As String) As Boolean
            Dim I As Short
            Dim X As Short
            Dim tSDIF_type As String
            Dim tField As String
            Dim tFoundField As String = ""
            Dim tCNTRY As String
            Dim tTmp As String

            Check_SDIF = False

            Try
                ' Check for A0, C1, etc....
                If Check_SDIF_Type(tStr) = True Then
                    SDIF_Error("Invalid type.", 1, 2, SDIF_CRITICAL)
                Else
                    tSDIF_type = Left(tStr, 2)
                    For I = 0 To UBound(gsType) - 1
                        If tSDIF_type = gsType(I) Then
                            X = 0
                            tCNTRY = ""
                            While giStart(I, X) <> 0
                                tField = GetSDIF(tStr, giStart(I, X), giLength(I, X))
                                If Len(tField) = 0 Then
                                    If InStr(1, UCase(gsMandatory(I, X)), "M1") Then ' if mandatory
                                        SDIF_Error(IIf(Len(gsAttribute(I, X)), gsAttribute(I, X), gsVariable(I, X)) & " is mandatory(M1), must be included for the record to be useful.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    ElseIf InStr(1, UCase(gsMandatory(I, X)), "M2") Then  ' if mandatory
                                        SDIF_Error(IIf(Len(gsAttribute(I, X)), gsAttribute(I, X), gsVariable(I, X)) & " is mandatory(M2), M2 fields are necessary for the records to be processed by USS.", giStart(I, X), giLength(I, X), SDIF_WARNING)
                                    ElseIf InStr(1, UCase(gsMandatory(I, X)), "M3") Then  ' if mandatory
                                        SDIF_Error(IIf(Len(gsAttribute(I, X)), gsAttribute(I, X), gsVariable(I, X)) & " is mandatory(M3), M3 fields must be present for Hy-Tek to process.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "CONST" Then
                                    If tField <> gsVariable(I, X) Then
                                        SDIF_Error("Field must contain """ & gsVariable(I, X) & """ to be valid.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "LOGICAL" Then
                                    If ValidateNo(tField, "TF ") = False Then
                                        SDIF_Error("Logical field must contain either of ""F/T/<blank>"" to be valid.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "INT" Then
                                    If IsNumeric(tField) = False Then
                                        SDIF_Error(UCase(gsVariable(I, X)) & " isn't numeric.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    Else
                                        If InStr(1, tField, ".") Then
                                            SDIF_Error(UCase(gsVariable(I, X)) & " must not contain a period.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                        End If
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "DEC" Then
                                    If IsNumeric(tField) = False Then
                                        SDIF_Error(UCase(gsVariable(I, X)) & " isn't numeric.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "DATE" Then
                                    If IsaDate(tField) = False Then
                                        SDIF_Error(UCase(gsVariable(I, X)) & " isn't a valid DATE.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "TIME" Then
                                    If Len(tField) > 0 Then
                                        If CSngTime(tField) = -1 Then
                                            tTmp = My.Application.Info.DirectoryPath & "\Templates\" & gsVariable(I, X)
                                            If File.Exists(tTmp) = True Then
                                                If Check_Code(tTmp, tField, gsMandatory(I, X), tFoundField) = True Then
                                                    SDIF_Error(gsFType(I, X) & " field is not valid!", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                                End If
                                            Else
                                                SDIF_Error(UCase(gsFType(I, X)) & " isn't a valid time.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                            End If
                                        End If
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "NAME" Then
                                    ' LastName, FName Initial
                                ElseIf UCase(gsFType(I, X)) = "CNTRY" Then
                                    tTmp = My.Application.Info.DirectoryPath & "\Templates\" & gsVariable(I, X)
                                    If File.Exists(tTmp) = True Then
                                        If Check_Code(tTmp, tField, gsMandatory(I, X), tCNTRY) = True Then
                                            SDIF_Error(gsVariable(I, X) & " isn't a valid CNTRY.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                        End If
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "STATE" Then
                                    If tCNTRY.Length > 0 Then
                                        tTmp = My.Application.Info.DirectoryPath & "\Templates\" & String.Format(gsVariable(I, X), tCNTRY)
                                        If File.Exists(tTmp) = True Then
                                            If Check_Code(tTmp, tField, gsMandatory(I, X), tFoundField) = True Then
                                                SDIF_Error(gsFType(I, X) & String.Format(" isn't a valid STATE in {0}.", tCNTRY), giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                            End If
                                        End If
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "USSNUM" Then
                                    If tCNTRY = "USA" Then
                                        If ValidUSSNUM(tField) = False Then
                                            SDIF_Error(UCase(gsVariable(I, X)) & " isn't a valid USSNUM.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                        End If
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "POSTAL" Then
                                    If tFoundField = "USA" Then
                                        If ValidateNo(tField, "1234567890- ") = False Then
                                            SDIF_Error(UCase(gsVariable(I, X)) & " isn't a valid POSTAL CODE.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                        End If
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "PHONE" Then
                                    If ValidateNo(tField, "1234567890+- ") = False Then
                                        SDIF_Error(UCase(gsVariable(I, X)) & " isn't a valid PHONE.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "ALPHA" Then
                                    If ValidateNo(tField, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqurstuvwxyz1234567890 ") = False Then
                                        SDIF_Error(UCase(gsVariable(I, X)) & " isn't a valid ALPHA.", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "FUTURE" Then
                                    If Len(tField) <> 0 Then
                                        SDIF_Error("Field is reserved for future use and should be blank.", giStart(I, X), giLength(I, X), SDIF_INFORMATIONAL)
                                    End If
                                ElseIf UCase(gsFType(I, X)) = "CODE" Then
                                    If InStr(1, gsMandatory(I, X), "M") = 0 And Len(tField) = 0 Then
                                        ' check next
                                    Else
                                        If Len(gsVariable(I, X)) = 0 Then
                                            If Len(gsAttribute(I, X)) > 0 Then
                                                If Check_Field(tField, gsAttribute(I, X)) = True Then
                                                    SDIF_Error(UCase(gsAttribute(I, X)) & " field is not valid!", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                                End If
                                            End If
                                        Else
                                            tTmp = My.Application.Info.DirectoryPath & "\Templates\" & gsVariable(I, X)
                                            If File.Exists(tTmp) = True Then
                                                If Check_Code(tTmp, tField, gsMandatory(I, X), tFoundField) = True Then
                                                    SDIF_Error(gsVariable(I, X) & " field is not valid!", giStart(I, X), giLength(I, X), SDIF_CRITICAL)
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    MsgBox("Invalid type = " & gsFType(I, X), MsgBoxStyle.Critical)
                                    End If
                                X = X + 1
                            End While
                            ' Exit For
                        End If
                    Next I
                End If
            Catch ex As Exception
                MsgBox("Error during SDIF check : " & ex.Message)
                Check_SDIF = True
            End Try

        End Function

        Function ValidateNo(ByVal NumStr As String, ByVal Pattern As String) As Boolean
            Dim Idx As Short
            Dim Match As Boolean
            Dim Idx1 As Short

            For Idx = 0 To NumStr.Length - 1
                Dim cChr As Char = NumStr.Substring(Idx, 1)
                For Idx1 = 0 To Pattern.Length - 1
                    If cChr = Pattern.Substring(Idx1, 1) Then
                        Match = True
                    End If
                Next Idx1
                If Match = False Then
                    Return False
                End If
            Next Idx

            Return True
        End Function

        ' mmddyyfffmllll
        Function ValidUSSNUM(ByVal tField As String) As Boolean
            Dim dt As DateTime
            Dim tDate As String = tField.Substring(0, 6)
            Dim result As Boolean = DateTime.TryParseExact(tDate, "MMddyy", CultureInfo.CurrentCulture, DateTimeStyles.None, dt)

            If result = False Then
                Return False
            End If

            If tField.Length > 14 Then
                Return False
            End If

            Dim tName As String = tField.Substring(6)
            Dim Idx As Short
            Dim Match As Boolean = False

            For Idx = 0 To tName.Length - 1
                Dim cChr As Char = tName.Substring(Idx, 1)
                If Char.IsLetter(cChr) = True Or cChr = "*" Then
                    Match = True
                End If
                If Match = False Then
                    Return False
                End If
            Next Idx

            Return True
        End Function

        Function Check_Field(ByRef tField As String, ByRef tName As String) As Boolean
            Dim tStr As String
            Dim I As Short

            On Error Resume Next

            Check_Field = False

            If UCase(tName) = "EVENTAGE" Then
                tStr = Left(tField, 2)
                If tStr = "UN" Then
                    tStr = Mid(tField, 3, 2)
                    If tStr <> "OV" Then
                        If IsNumeric(tStr) = False Then
                            Check_Field = True
                        End If
                    End If
                Else
                    tStr = Mid(tField, 3, 2)
                    If tStr = "OV" Then
                        tStr = Left(tField, 2)
                        If IsNumeric(tStr) = False Then
                            Check_Field = True
                        End If
                    Else
                        If IsNumeric(tField) = False Then
                            Check_Field = True
                        End If
                    End If
                End If

            ElseIf UCase(tName) = "ETHNICITY" Then

                For I = 1 To Len(tField)
                    tStr = Mid(tField, I, 1)
                    If InStr(1, "QRSUVWX", tStr) Then
                        ' okay
                    Else
                        Check_Field = True
                    End If
                Next I
                tStr = Left(tField, 1)
                If InStr(1, "VWX", tStr) Then
                    If Len(tField) > 1 Then
                        Check_Field = True
                    End If
                End If

            ElseIf UCase(tName) = "CLASSKEY" Then

                For I = 1 To Len(tField)
                    tStr = Mid(tField, I, 1)
                    If InStr(1, "UO12P3456JS ", tStr) > 0 Then
                        If I = 1 And tStr = "O" Then
                            Check_Field = True
                        ElseIf I = 2 And tStr = "U" Then
                            Check_Field = True
                        End If
                    Else
                        Check_Field = True
                    End If
                Next I
            Else
                SDIF_Error("SDIF control template problem with " & tName & " field.", 0, 0, SDIF_CRITICAL)
            End If

        End Function

        Function Check_Code(ByVal tCodeFile As String, ByVal tStr As String, ByVal tMandatory As String, ByRef tField As String) As Boolean
            Dim tTmp As String
            Dim FileNumber As Short

            Check_Code = False
            FileNumber = FreeFile()
            Try
                FileOpen(FileNumber, tCodeFile, OpenMode.Input)
                Try
                    Check_Code = True
                    Do While Not EOF(FileNumber)
                        tTmp = LineInput(FileNumber)
                        tField = GetField(0, tTmp)
                        If tField = Right(tStr, Len(tField)) Then
                            Check_Code = False
                            Exit Do
                        End If
                    Loop
                Catch ex As Exception
                    MsgBox(String.Format("Search error on {0} : Error : {1}", tCodeFile, ex.Message))
                Finally
                    FileClose(FileNumber)
                End Try
            Catch ex As Exception
                MsgBox(String.Format("Open error on {0} : Error : {1}", tCodeFile, ex.Message))
            End Try

        End Function

        Function GetSDIF(ByRef tStr As String, ByRef tStart As Short, ByRef tLen As Short) As String
            GetSDIF = RTrim(Mid(tStr, tStart, tLen))
        End Function

        Function Check_SDIF_Type(ByRef tStr As String) As Boolean
            Dim tSDIF_type As String
            Dim I As Short

            On Error Resume Next

            tSDIF_type = Left(tStr, 2)
            For I = 0 To UBound(gsType) - 1
                If tSDIF_type = gsType(I) Then
                    gsTypePresent(I) = True
                    If giSDIFRec = 0 Then
                        If UCase(tSDIF_type) <> "A0" Then
                            SDIF_Error("First record must be an ""A0"" type.", 1, 2, SDIF_CRITICAL)
                        End If
                    End If
                    Check_SDIF_Type = False
                    Exit Function
                End If
            Next I

            Check_SDIF_Type = True

        End Function

        Function SDIF_Error(ByRef tmsg As String, ByRef tcol As Short, ByRef tLen As Short, ByRef tErr As Short) As Short
            Dim tStr As String = ""
            Dim tTmp As String = ""

            Try
                Dim c As Color
                Select Case tErr
                    Case SDIF_WARNING
                        tTmp = "Warning : "
                        c = Color.DarkOrange
                    Case SDIF_CRITICAL
                        tTmp = "Critical : "
                        c = Color.Red
                    Case SDIF_INFORMATIONAL
                        tTmp = "Informational : "
                        c = Color.DarkBlue
                End Select

                If frmMain.mnuViewWarnings.Checked = True Then 'suppress warnings
                    If tErr <= SDIF_WARNING Then
                        Exit Function
                    End If
                End If

                giSDIFRecMax = giSDIFRecMax + 1
                tStr = tTmp & tmsg & " (column=" & CStr(tcol) & ", length=" & CStr(tLen) & ")"
                If tErr > giError Then
                    giError = tErr
                End If

                Dim sSubString As String = ""

                Try
                    If tcol < sDGVRow.Length Then
                        sSubString = sDGVRow.Substring(tcol - 1, Min(tLen, sDGVRow.Length - tcol))
                    End If
                Catch ex As Exception
                    sSubString = " "
                End Try

                Dim Row1 As String() = {"", tStr & " >>" & sSubString & "<<"}

                iDGVRow += 1
                iDGVMaxRow += 1
                frmMain.DataGridView1.Rows.Insert(iDGVRow, Row1)
                Dim dr As DataGridViewRow = frmMain.DataGridView1.Rows(iDGVRow)

                'dr.DefaultCellStyle.BackColor = Color.LightGray
                dr.DefaultCellStyle.ForeColor = c
                dr.DefaultCellStyle.Font = New Font("Tahoma", 8, FontStyle.Bold)

                giSDIFRec = giSDIFRec + 1

                SDIF_Error = tErr

                SDIFErrorCount += 1
            Catch ex As Exception

            End Try

        End Function
    End Module
End Namespace